package com.zyao89.view.zloading.star;

import com.zyao89.view.zloading.ZLoadingBuilder;
import com.zyao89.view.zloading.util.NumCalcUtil;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.render.Canvas;
import ohos.agp.render.ColorFilter;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

/**
 * Created by zyao89 on 2017/3/20.
 * Contact me at 305161066@qq.com or zyao89@gmail.com
 * For more projects: https://github.com/zyao89
 * My Blog: http://zyao89.me
 */
public class StarBuilder extends ZLoadingBuilder {

    // 定义日志标签
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "zLoading MainAbilitySlice");
    private Paint mFullPaint;
    private float mStarOutR;
    private float mStarInR;
    private float mStarOutMidR;
    private float mStarInMidR;

    // 开始偏移角度
    private int mStartAngle;
    private Path mStarPath;
    private double mOffsetTranslateY;
    private RectFloat mOvalRectF;
    private double mShadowWidth;
    private AnimatorValue mShadowAnimator;

    private final AnimatorValue.ValueUpdateListener mAnimatorUpdateListener = new AnimatorValue.ValueUpdateListener() {
        @Override
        public void onUpdate(AnimatorValue animatorValue, float v) {
            mOffsetTranslateY = getViewCenterY() * 0.4f * v;
            mShadowWidth = (mOffsetTranslateY + 10) * (double) 0.9f;
        }

    };

    @Override
    protected void initParams(Context context, Color color) {
        mFullPaint = new Paint();
        mFullPaint.setStyle(Paint.Style.FILLANDSTROKE_STYLE);
        mFullPaint.setStrokeWidth(2);
        mFullPaint.setColor(color);
        mFullPaint.setDither(true);
        mFullPaint.setFilterBitmap(true);
        initValue(context);
        initAnimator();
    }

    private void initAnimator() {
        mShadowAnimator = new AnimatorValue();
        mShadowAnimator.setLoopedCount(Animator.INFINITE);
        mShadowAnimator.setDuration(getAnimationDuration());
        mShadowAnimator.setDelay(getAnimationStartDelay());
        mShadowAnimator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
    }

    private void initValue(Context context) {
        double allSize = getAllSize();
        mStarOutR = (float) (allSize - dip2px(context, 5));
        mStarOutMidR = mStarOutR * 0.9f;
        mStarInR = mStarOutMidR * 0.6f;
        mStarInMidR = mStarInR * 0.9f;
        mStartAngle = 0;
        mOffsetTranslateY = 0;

        // 星路径
        mStarPath = createStarPath(5, -18);

        // 阴影宽度
        mShadowWidth = mStarOutR;
        mOvalRectF = new RectFloat();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.save();
        canvas.translate(0, (float) mOffsetTranslateY);
        canvas.rotate(mStartAngle, getViewCenterX(), getViewCenterY());
        canvas.drawPath(mStarPath, mFullPaint);
        canvas.restore();
        mOvalRectF.fuse((float)((double)getViewCenterX() - mShadowWidth), (float) ((double)getIntrinsicHeight() - 20), (float)((double)getViewCenterX() + mShadowWidth), (float) ((double)getIntrinsicHeight() - 10));
        canvas.drawOval(mOvalRectF, mFullPaint);
    }

    /**
     * 绘制五角星
     *
     * @param num 角数量
     * @param startAngle 初始角度
     * @return 五角星的路线
     */
    private Path createStarPath(int num, int startAngle) {
        final Path path = new Path();
        int angle = 360 / num;
        int roundSize = 5;
        int offsetAngle = angle / 2;
        path.moveTo(NumCalcUtil.add(getViewCenterX(), mStarOutMidR * cos(startAngle - roundSize)),
            (float) ((double)getViewCenterY() + mStarOutMidR * sin(startAngle - roundSize)));
        for (int i = 0; i < num; i++) {
            int value = angle * i + startAngle;
            path.lineTo(NumCalcUtil.add(getViewCenterX(), mStarOutMidR * cos(value - roundSize)),
                (float) ((double)getViewCenterY() + mStarOutMidR * sin(value - roundSize)));

            // 圆角
            path.quadTo((float) ((double)getViewCenterX() + mStarOutR * cos(value)), (float) ((double)getViewCenterY()
                                        + mStarOutR * sin(value)), (float) ((double)getViewCenterX()
                                                                    + mStarOutMidR * cos(value + roundSize)),
                (float) ((double)getViewCenterY() + mStarOutMidR * sin(value + roundSize)));
            path.lineTo((float) ((double)getViewCenterX() + mStarInR * cos(value + offsetAngle - roundSize)),
                (float) ((double)getViewCenterY() + mStarInR * sin(value + offsetAngle - roundSize)));

            // 内圆角
            path.quadTo((float) ((double)getViewCenterX() + mStarInMidR * cos(value + offsetAngle)),
                (float) ((double)getViewCenterY() + mStarInMidR * sin(value + offsetAngle)), (float) ((double)getViewCenterX()
                                            + mStarInR * cos(value + offsetAngle + roundSize)),
                (float) ((double)getViewCenterY() + mStarInR * sin(value + offsetAngle + roundSize)));
        }
        path.close();
        return path;
    }

    @Override
    protected void setAlpha(int alpha) {
        mFullPaint.setAlpha(alpha);
    }

    @Override
    protected void prepareStart(AnimatorValue floatValueAnimator) {
        floatValueAnimator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);

        mShadowAnimator.setLoopedCount(Animator.INFINITE);
        mShadowAnimator.setDuration(getAnimationDuration());
        mShadowAnimator.setDelay(getAnimationStartDelay());
        mShadowAnimator.setValueUpdateListener(mAnimatorUpdateListener);
        mShadowAnimator.start();
    }

    @Override
    protected void prepareEnd() {
        mShadowAnimator.release();
        mShadowAnimator.setLoopedCount(0);
        mShadowAnimator.setDuration(0);
        mShadowAnimator.end();
    }

    @Override
    protected void computeUpdateValue(AnimatorValue animation, float animatedValue) {
        mStartAngle = (int) (360 * animatedValue);
    }

    @Override
    protected void setColorFilter(ColorFilter colorFilter) {
        mFullPaint.setColorFilter(colorFilter);
    }

    protected final float cos(int num) {
        return (float) Math.cos(num * Math.PI / 180);
    }

    protected final float sin(int num) {
        return (float) Math.sin(num * Math.PI / 180);
    }

    @Override
    public void onRepeat(Animator animator) {

    }
}
